package org.budo.support.lang.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import org.budo.support.slf4j.Slf4j;
import org.slf4j.Logger;

/**
 * @author lmw
 */
public class PropertiesUtil {
    private static final Logger log = Slf4j.getLogger();

    public static String getProperty(Properties properties, String key, String defaultValue) {
        if (null == properties || properties.isEmpty()) {
            return defaultValue;
        }

        String value = properties.getProperty(key);
        if (StringUtil.isEmpty(value) || "null".equalsIgnoreCase(value)) {
            return defaultValue;
        }

        return value;
    }

    public static Properties load(String path) {
        if (null == path) {
            log.error("#36 load, path=" + path);
            return null;
        }

        Boolean exists = FileUtil.exists(path);
        if (!exists) {
            log.warn("#42 " + path + " not exists, canonicalPath=" + FileUtil.getCanonicalPath(new File(path)));
            return new Properties();
        }

        FileInputStream inputStream = IoUtil.fileInputStream(path);
        Properties properties = load(inputStream);
        return properties;
    }

    public static Properties load(InputStream inputStream) {
        if (null == inputStream) {
            return null;
        }

        return load(new Properties(), inputStream);
    }

    public static Properties load(Properties properties, InputStream inputStream) {
        try {
            properties.load(inputStream);
            inputStream.close();
            return properties;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static Properties fromMap(Map<String, Object> map) {
        if (null == map) {
            return null;
        }

        Properties properties = new Properties();
        Set<Entry<String, Object>> entrySet = map.entrySet();
        for (Entry<String, Object> entry : entrySet) {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (null == key || null == value) {
                log.warn("#56 fromMap null value, key=" + key + ", value=" + value);
            } else {
                properties.put(key, value);
            }
        }

        return properties;
    }

    public static String loadProperty(File file, String key) {
        FileInputStream inputStream = IoUtil.fileInputStream(file);
        Properties properties = load(inputStream);

        if (null == properties || properties.isEmpty() || null == key || key.isEmpty()) {
            log.error("#95 loadProperty return null, file=" + file + ", properties=" + properties + ", key=" + key);
            return null;
        }

        String value = properties.getProperty(key);
        if (null == value || value.isEmpty()) {
            log.warn("#101 loadProperty value=" + value + ", key=" + key + ", file=" + file);
        }

        return value;
    }

    public static String loadProperty(String path, String key) {
        Properties properties = load(path);

        if (null == properties || properties.isEmpty() || null == key || key.isEmpty()) {
            log.error("#111 loadProperty return null, path=" + path + ", properties=" + properties + ", key=" + key);
            return null;
        }

        String value = properties.getProperty(key);
        if (null == value || value.isEmpty()) {
            log.warn("#117 loadProperty value=" + value + ", key=" + key + ", path=" + path);
        }

        return value;
    }

    public static Integer loadPropertyInteger(String path, String key) {
        String loadProperty = loadProperty(path, key);
        Integer val = NumberUtil.toInteger(loadProperty);
        return val;
    }

    public static Boolean hasKey(String properties) {
        if (null == properties || properties.trim().isEmpty()) {
            return false;
        }

        Properties props = load(new ByteArrayInputStream(properties.getBytes()));
        return !props.isEmpty();
    }
}